/**********************************************************************************
 * Copyright (c) 2015, Freescale Semiconductor, Inc.
 * Copyright 2016-2017 NXP
 * All rights reserved.
 *
 *
 * This is the Function Lib module header file
 *
 * SPDX-License-Identifier: BSD-3-Clause
 ********************************************************************************** */

#ifndef FUNCTION_LIB_H
#define FUNCTION_LIB_H

#include "EmbeddedTypes.h"

/*!
 * @addtogroup FunctionLib
 * The FunctionLib module
 *
 * This module provides a collection of features commonly used in embedded software centered on memory manipulation.
 * @{
 */

/**********************************************************************************
*************************************************************************************
* Public macros
*************************************************************************************
********************************************************************************** */

#ifndef gUseToolchainMemFunc_d
/* [/BLUETOOTH-8395] This is a temporary fix to overcome the issue causing HF(unaligned) when using MCUX */
#if defined(__GNUC__)
#define gUseToolchainMemFunc_d 0
#else
#define gUseToolchainMemFunc_d 1
#endif /* __GNUC__ */
#endif

#ifndef gFLib_CheckBufferOverflow_d
#define gFLib_CheckBufferOverflow_d 0
#endif

#define FLib_MemSet16 FLib_MemSet

/**********************************************************************************
*************************************************************************************
* Public prototypes
*************************************************************************************
********************************************************************************** */

/**********************************************************************************
*************************************************************************************
* Public type definitions
*************************************************************************************
********************************************************************************** */

/**********************************************************************************
*************************************************************************************
* Public memory declarations
*************************************************************************************
********************************************************************************** */

/**********************************************************************************
*************************************************************************************
* Public functions
*************************************************************************************
********************************************************************************** */

#ifdef __cplusplus
extern "C" {
#endif

/*! *********************************************************************************
 * \brief  Copy the content of one memory block to another. The amount of data to copy
 *         must be specified in number of bytes.
 *
 * \param[out] pDst    Pointer to destination memory block
 * \param[in]  pSrc    Pointer to source memory block
 * \param[in]  cBytes  Number of bytes to copy
 ********************************************************************************** */
void FLib_MemCpy(void *pDst, const void *pSrc, uint32_t cBytes);

/*! *********************************************************************************
 * \brief  Copy the content of one memory block to another. The amount of data to copy
 *         must be specified in number of bytes.
 *
 * \param[out] to_ptr           Pointer to destination memory block
 * \param[in]  from_ptr         Pointer to source memory block
 * \param[in]  number_of_bytes  Number of bytes to copy
 ********************************************************************************** */
void FLib_MemCpyAligned32bit(void *to_ptr, const void *from_ptr, register uint32_t number_of_bytes);

/*! *********************************************************************************
 * \brief  Copy the content of one memory block to another. The amount of data to copy
 *         must be specified in number of bytes.
 *
 * \param[out] pBuf1   Pointer to a memory buffer
 * \param[out] pBuf2   Pointer to a memory buffer
 * \param[in]  dir     Copying direction
 * \param[in]  n       Number of bytes to copy
 ********************************************************************************** */
void FLib_MemCpyDir(void *pBuf1, void *pBuf2, bool_t dir, uint32_t n);

/*! *********************************************************************************
 * \brief  Copy bytes. The byte at index i from the source buffer is copied to index
 *         ((n-1) - i) in the destination buffer (and vice versa).
 *
 * \param[out] pDst    Pointer to destination memory block
 * \param[in]  pSrc    Pointer to source memory block
 * \param[in]  cBytes  Number of bytes to copy
 ********************************************************************************** */
void FLib_MemCpyReverseOrder(void *pDst, const void *pSrc, uint32_t cBytes);

/*! *********************************************************************************
 * \brief  Compare two memory blocks. The number of bytes to compare must be specified.
 *         If the blocks are equal byte by byte, the function returns TRUE,
 *         and FALSE otherwise.
 *
 * \param[in] pData1  First memory block to compare
 * \param[in] pData2  Second memory block to compare
 * \param[in] cBytes  Number of bytes to compare
 *
 * \return  TRUE if memory areas are equal. FALSE otherwise.
 ********************************************************************************** */
bool_t FLib_MemCmp(const void *pData1, const void *pData2, uint32_t cBytes);

/*! *********************************************************************************
* \brief  Compare each byte of a memory block to a given value. The number of bytes to compare
          must be specified.
*         If all the bytes are equal to the given value, the function returns TRUE,
*         and FALSE otherwise.
*
* \param[in] pAddr   Location to be compared
* \param[in] val     Reference value
* \param[in] len  Number of bytes to compare
*
* \return  TRUE if all bytes match and FALSE otherwise.
********************************************************************************** */
bool_t FLib_MemCmpToVal(const void *pAddr, uint8_t val, uint32_t len);

/*! *********************************************************************************
 * \brief  Reset bytes in a memory block to a certain value. The value, and the number
 *         of bytes to be set, are supplied as arguments.
 *
 * \param[in] pData   Pointer to memory block to reset
 * \param[in] value   Value that memory block will be set to
 * \param[in] cBytes  Number of bytes to set
 ********************************************************************************** */
void FLib_MemSet(void *pData, uint8_t value, uint32_t cBytes);

/*! *********************************************************************************
 * \brief  This function sets all words in a specified buffer to a set value.
 *   The memory set is done word per word
 *
 * \param[in,out]  pData  Address of the buffer to set.
 * \param[in]  value  Set value.
 * \param[in]  cWords Number of words to set in the buffer.
 *
 ********************************************************************************** */
void FLib_MemSet32Aligned(void *pData, uint32_t value, uint32_t cWords);

/*! *********************************************************************************
 * \brief Copy bytes, possibly into the same overlapping memory as it is taken from
 *
 * \param[out] pDst   Pointer to destination memory block
 * \param[in] pSrc    Pointer to source memory block
 * \param[in] cBytes  Number of bytes to copy
 ********************************************************************************** */
void FLib_MemInPlaceCpy(void *pDst, void *pSrc, uint32_t cBytes);

/*! *********************************************************************************
 * \brief  Copies a 16bit value to an unaligned a memory block.
 *
 * \param[out] pDst   Pointer to destination memory block
 * \param[in] val16   The 16-bit value to be copied
 ********************************************************************************** */
void FLib_MemCopy16Unaligned(void *pDst, uint16_t val16);

/*! *********************************************************************************
 * \brief  Copies a 32bit value to an unaligned a memory block.
 *
 * \param[out] pDst   Pointer to destination memory block
 * \param[in] val32   The 32-bit value to be copied
 ********************************************************************************** */
void FLib_MemCopy32Unaligned(void *pDst, uint32_t val32);

/*! *********************************************************************************
 * \brief  Copies a 64bit value to an unaligned a memory block.
 *
 * \param[out] pDst   Pointer to destination memory block
 * \param[in] val64   The 64-bit value to be copied
 ********************************************************************************** */
void FLib_MemCopy64Unaligned(void *pDst, uint64_t val64);

/*! *********************************************************************************
 * \brief Add an offset to a pointer.
 *
 * \param[out] pPtr   Pointer to the pointer to be updated
 * \param[in] offset  The offset(in bytes) to be added
 ********************************************************************************** */
void FLib_AddOffsetToPointer(void **pPtr, uint32_t offset);

/*! *********************************************************************************
 * \brief  This function returns the length of a NULL terminated string.
 *
 * \param[in]  str  A NULL terminated string
 *
 * \return  the size of string in bytes
 ********************************************************************************** */
uint32_t FLib_StrLen(const char *str);

/*! *********************************************************************************
 * \brief  Compare two bytes.
 *
 * \param[in] pCmp1  pointer to the first 2-byte compare value
 * \param[in] pCmp2  pointer to the second 2-byte compare value
 *
 * \return  TRUE if the two bytes are equal, and FALSE otherwise.
 ********************************************************************************** */
#define FLib_Cmp2Bytes(pCmp1, pCmp2) \
    ((((uint8_t *)(pCmp1))[0] == ((uint8_t *)(pCmp2))[0]) && (((uint8_t *)(pCmp1))[1] == ((uint8_t *)(pCmp2))[1]))

/*! *********************************************************************************
 * \brief  Returns the maximum value of arguments a and b.
 *
 * \return  The maximum value of arguments a and b
 *
 * \remarks
 *   The primitive must be implemented as a macro, as it should be possible to
 *   evaluate the result on compile time if the arguments are constants.
 ********************************************************************************** */
#define FLib_GetMax(a, b) (((a) > (b)) ? (a) : (b))

/*! *********************************************************************************
 * \brief  Returns the minimum value of arguments a and b.
 *
 * \return  The minimum value of arguments a and b
 *
 * \remarks
 *   The primitive must be implemented as a macro, as it should be possible to
 *   evaluate the result on compile time if the arguments are constants.
 ********************************************************************************** */
#define FLib_GetMin(a, b) (((a) < (b)) ? (a) : (b))

/*! *********************************************************************************
 * \brief  Copy bytes. The byte at index i from the buffer is copied to index
 *         ((n-1) - i) in the same buffer (and vice versa).
 *         Used for endianess conversion of octet strigs.
 *
 * \param[out] buf     Pointer to destination memory block to be byte reversed.
 * \param[in]  cBytes  Number of bytes to copy
 *
 * \remarks
 *       If the size is a multiple of 4 bytes, the operation is done word by word.
 *       Assumes that pBuf is word aligned.
 ********************************************************************************** */
void FLib_ReverseByteOrderInPlace(void *buf, uint32_t cBytes);

/*! *********************************************************************************
 * \brief Copy  4 bytes (word) from source to destination
 *
 * \param[in, out]  pDst Pointer to destination integer on 32 bits.
 *
 * \param[in]  pSrc Pointer to source memory block
 *
 * \note Useful to avoid MISRA rule 11.3 strict aliaising warning in the code when casting pointer to 8 bits structure
 *       to 32bits
 *
 ********************************************************************************** */
static inline void FLib_MemCpyWord(void *pDst, void *pSrc)
{
    *((uint32_t *)pDst) = *((uint32_t *)pSrc);
}
/*!
 * @}  end of FunctionLib addtogroup
 */

#ifdef __cplusplus
}
#endif

#endif /* FUNCTION_LIB_H */
